import React, { useState, useCallback, useRef, useLayoutEffect, } from 'react'
import { connect } from 'react-redux'
import { LogStatus, LogTypes } from '../../common/enums'
import {
    getProgressActiveSuiteSelector, getProgressActiveSuiteLogsSelector,
    getProgressActivePlanActiveSuiteJsErrorLogsSelector,
    getProgressActivePlanIdSelector,
    getProgressActiveSuiteStepListSelector
} from '../../selectors/baseSelector'
import basicStyle from '../common/basic.scss'
import { clearData, updateLogRemark } from '../../source/saveData'
import { StepEngine } from '../../consts/stepEngine'
import { CostTime } from '../common/costTime'
import { EmptyElement } from '../common/emptyElement'
import { Tabs } from '../common/tabs'
import { jsErrorLogRender } from './jsErrorLog'
import { ProgressMark } from '../common/progressMark'
import { ScreenShotViewer } from '../common/screenShotViewer'
import { getIfStepResultValid } from '../../common/getIfStepResultValid'
import { mergeStyle } from '../common/mergeStyle'
import classnames from 'classnames'
import { ColHeader } from '../common/colHeader'
import { ErrorMark } from '../common/errorMark'
// import { useClearData } from '../common/useClearData'

const maStateToProps = state => {
    return {
        activePlanId: getProgressActivePlanIdSelector(state),
        activeSuiteLogs: getProgressActiveSuiteLogsSelector(state),
        activeSuiteStepList: getProgressActiveSuiteStepListSelector(state),
        activeSuiteJsErrorLogs: getProgressActivePlanActiveSuiteJsErrorLogsSelector(state)
    }
}

const mapDispatchToProps = dispatch => {
    return {
        clearData: (collection) => clearData(collection),
        updateLogRemark: (id, remark) => updateLogRemark(id, remark)
    }
}

export const ProgressDetail = connect(maStateToProps, mapDispatchToProps)((props) => {
    const { activePlanId, activeSuiteLogs, activeSuiteJsErrorLogs, updateLogRemark, activeSuiteStepList: stepList } = props
    const [activeTab, setActiveTab] = useState('logs')

    const allSuiteLogs = activeSuiteLogs.filter(log => log.type === LogTypes.suite)
    const allStepLogs = activeSuiteLogs.filter(log => log.type === LogTypes.step)

    const suiteStartLog = allSuiteLogs.find(log => log.status === LogStatus.start)
    const suiteEndLog = allSuiteLogs.find(log => log.status !== LogStatus.start)
    const startAt = suiteStartLog ? suiteStartLog.date : 0
    const endAt = suiteEndLog ? suiteEndLog.date : +(new Date())
    const rawRemarkEditor = { id: '', x: 0, y: 0, remark: undefined }
    const [remarkEditor, setRemarkEditor] = useState(rawRemarkEditor)
    const [localRemarks, setLocalRemarks] = useState({})
    const remarkEditorRef = useRef()
    const logListRef = useRef()

    useLayoutEffect(() => {
        if (remarkEditorRef.current) {
            remarkEditorRef.current.focus()
        }
    }, [remarkEditorRef.current])

    const tabs = [
        {
            title: '步骤',
            name: 'logs',
            content: <div className={basicStyle.scroll_list} ref={logListRef}>
                <CostTime alwayVisible={true} prefix={(startAt ? `${new Date(startAt).toLocaleString()}` : '')
                    + (startAt && endAt ? ` ~ ${new Date(endAt).toLocaleString()}` : '')
                    + '    总耗时：'} elapse={startAt ? (endAt - startAt) : 0}
                />
                {stepList.length ? stepList
                    .map((step, index) => {
                        const { id: stepId } = step
                        const stepLogs = allStepLogs.filter(entry => entry.stepId === stepId)  //对于一个步骤，最多只有两条日志，一条开始，一条结束
                        const startLog = stepLogs.find(log => log.status === LogStatus.start)
                        const startLogId = startLog ? startLog.id : ''
                        const startLogRemark = startLog ? (typeof localRemarks[startLogId] !== 'undefined' ? localRemarks[startLogId] : startLog.remark) : ''
                        const nonStartLogs = stepLogs.filter(log => log.status !== LogStatus.start)
                        const endLog = nonStartLogs.find(log => log.status !== LogStatus.pending) || nonStartLogs.find(log => log.status === LogStatus.pending)

                        const result = endLog && typeof endLog.result !== 'undefined' ? endLog.result : {}
                        const screenshotId = endLog ? endLog.screenshotId : ''
                        const status = endLog ? endLog.status : (startLog ? startLog.status : '')
                        const elapse = startLog ? ((endLog ? endLog.date : +new Date()) - startLog.date) : 0
                        const error = endLog ? endLog.error : ''
                        const stepEngine = StepEngine[step.code]
                        const valid = getIfStepResultValid(step.code, result)
                        const isEditingRemark = remarkEditor.id && remarkEditor.id === startLogId

                        return <div key={`${stepId}_${index}`} className={mergeStyle(basicStyle, 'progress_entry', classnames({ editing: isEditingRemark }))}>
                            {index + 1}.
                            <ProgressMark status={status} valid={valid} />
                            {stepEngine.renderLog({ data: step.data, result, status, elapse, screenshotId, planId: activePlanId, stepId, valid })}
                            {(!stepEngine.renderWholeLog || !stepEngine.renderWholeLog({ data: step.data, result })) && (
                                <React.Fragment>
                                    <CostTime elapse={elapse} />
                                    <ScreenShotViewer planId={activePlanId} stepId={stepId} screenshotId={screenshotId} />
                                </React.Fragment>)}
                            <span className={mergeStyle(basicStyle, 'log_entry', 'log_remark')} title={startLogRemark}>{startLogRemark}</span>
                            {error && <ErrorMark tip={error} />}
                            {isEditingRemark
                                ? <React.Fragment>
                                    <div>
                                        <span onClick={ev => {
                                            const remark = (remarkEditor.remark || '').trim()
                                            updateLogRemark(startLogId, remark)
                                            setRemarkEditor(rawRemarkEditor)
                                            setLocalRemarks(current => ({ ...current, [startLogId]: remark }))
                                        }} title={'保存备注'} className={mergeStyle(basicStyle, classnames('icon', 'tick'))} />
                                        <span onClick={ev => {
                                            setRemarkEditor(rawRemarkEditor)
                                        }} title={'取消'} className={mergeStyle(basicStyle, classnames('icon', 'cross'))} />
                                    </div>
                                    <textarea ref={remarkEditorRef} style={{ left: remarkEditor.x, top: remarkEditor.y }}
                                        className={mergeStyle(basicStyle, 'log_remark_editor')}
                                        value={typeof remarkEditor.remark === 'undefined' ? startLogRemark : remarkEditor.remark} onChange={ev => {
                                            const remark = ev.target.value
                                            ev.persist()
                                            setRemarkEditor(current => ({ ...current, remark: remark }))
                                        }}></textarea>
                                </React.Fragment>
                                : <span onClick={ev => {
                                    const { offsetLeft, offsetTop } = ev.target
                                    const logListEl = logListRef.current
                                    const editorWidth = 200

                                    setRemarkEditor({
                                        id: startLogId,
                                        remark: startLogRemark,
                                        x: (offsetLeft + editorWidth > logListEl.clientWidth) ? (logListEl.clientWidth - editorWidth - 70) : offsetLeft,
                                        y: offsetTop + 20 - logListEl.scrollTop,
                                    })
                                }} title={'备注'} className={mergeStyle(basicStyle, classnames('icon', 'edit'))} />}
                        </div>
                    }) : <EmptyElement />}
            </div>
        }, activeSuiteJsErrorLogs.length ? {
            title: 'js错误',
            name: 'error',
            content: <div>{activeSuiteJsErrorLogs.map(log => jsErrorLogRender(log))}</div>
        } : null
    ].filter(Boolean)

    const getTabName = useCallback(tab => tab.name, [])
    const getTabTitle = useCallback(tab => tab.title, [])
    const getTabContent = useCallback(tab => tab.content, [])
    const onActiveTab = useCallback(tabTitle => setActiveTab(tabTitle), [])

    return (
        <React.Fragment>
            {/* {useClearData()} */}
            <ColHeader title='运行结果：' />
            <Tabs activeCode={activeTab} items={tabs} getItemValue={getTabName} onActiveTab={onActiveTab}
                renderContent={getTabContent} renderTitle={getTabTitle} />
        </React.Fragment>
    )
})